{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 线性回归的概念"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1、线性回归的原理  \n",
    "  \n",
    "2、线性回归损失函数、代价函数、目标函数  \n",
    "  \n",
    "3、优化方法(梯度下降法、牛顿法、拟牛顿法等)  \n",
    "  \n",
    "4、线性回归的评估指标  \n",
    "  \n",
    "5、sklearn参数详解"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1、线性回归的原理\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "进入一家房产网，可以看到房价、面积、厅室呈现以下数据："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "<table>\n",
    "    <tr>\n",
    "        <th>面积($x_1$)</th>\n",
    "        <th>厅室数量($x_2)$</th>\n",
    "        <th>价格(万元)(y)</th>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <th>64</th>\n",
    "        <th>3</th>\n",
    "        <th>225</th>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <th>59</th>\n",
    "        <th>3</th>\n",
    "        <th>185</th>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <th>65</th>\n",
    "        <th>3</th>\n",
    "        <th>208</th>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <th>116</th>\n",
    "        <th>4</th>\n",
    "        <th>508</th>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <th>……</th>\n",
    "        <th>……</th>\n",
    "        <th>……</th>\n",
    "    </tr>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们可以将价格和面积、厅室数量的关系习得为$f(x)=\\theta_0+\\theta_1x_1+\\theta_2x_2$，使得$f(x)\\approx y$，这就是一个直观的线性回归的样式。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<td bgcolor=#87CEEB>\n",
    "    <font size =2>\n",
    "小练习：这是国内一个房产网站上任意搜的数据，有兴趣可以找个网站观察一下，还可以获得哪些可能影响到房价的因素？可能会如何影响到实际房价呢？</font>\n",
    "</td>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 线性回归的一般形式：\n",
    "有数据集$\\{(x_1,y_1),(x_2,y_2),...,(x_n,y_n)\\}$,其中,$x_i = (x_{i1};x_{i2};x_{i3};...;x_{id}),y_i\\in R$<br> \n",
    "其中n表示变量的数量，d表示每个变量的维度。  \n",
    "可以用以下函数来描述y和x之间的关系："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\\begin{align*}\n",
    "f(x) \n",
    "&= \\theta_0 + \\theta_1x_1 + \\theta_2x_2 + ... + \\theta_dx_d  \\\\\n",
    "&= \\sum_{i=0}^{d}\\theta_ix_i \\\\\n",
    "\\end{align*}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如何来确定$\\theta$的值，使得$f(x)$尽可能接近y的值呢？均方误差是回归中常用的性能度量，即："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$J(\\theta)=\\frac{1}{2}\\sum_{j=1}^{n}(h_{\\theta}(x^{(i)})-y^{(i)})^2$$<br>  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们可以选择$\\theta$，试图让均方误差最小化："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 极大似然估计（概率角度的诠释）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "下面我们用极大似然估计，来解释为什么要用均方误差作为性能度量"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们可以把目标值和变量写成如下等式："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\n",
    "y^{(i)} = \\theta^T x^{(i)}+\\epsilon^{(i)}\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$\\epsilon$表示我们未观测到的变量的印象，即随机噪音。我们假定$\\epsilon$是独立同分布，服从高斯分布。（根据中心极限定理）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\n",
    "p(\\epsilon^{(i)}) = \\frac{1}{\\sqrt{2\\pi}\\sigma}exp\\left(-\\frac{(\\epsilon^{(i)})^2}{2\\sigma^2}\\right)$$\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "因此，"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\n",
    "p(y^{(i)}|x^{(i)};\\theta) = \\frac{1}{\\sqrt{2\\pi}\\sigma}exp\\left(-\\frac{(y^{(i)}-\\theta^T x^{(i)})^2}{2\\sigma^2}\\right)\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们建立极大似然函数，即描述数据遵从当前样本分布的概率分布函数。由于样本的数据集独立同分布，因此可以写成"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\n",
    "L(\\theta) = p(\\vec y | X;\\theta) = \\prod^n_{i=1}\\frac{1}{\\sqrt{2\\pi}\\sigma}exp\\left(-\\frac{(y^{(i)}-\\theta^T x^{(i)})^2}{2\\sigma^2}\\right)\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "选择$\\theta$，使得似然函数最大化，这就是极大似然估计的思想。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "为了方便计算，我们计算时通常对对数似然函数求最大值："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\\begin{align*}\n",
    "l(\\theta) \n",
    "&= log L(\\theta) = log \\prod^n_{i=1}\\frac{1}{\\sqrt{2\\pi}\\sigma}exp\\left(-\\frac{(y^{(i)}-\\theta^T x^{(i)})^2} {2\\sigma^2}\\right) \\\\\n",
    "& = \\sum^n_{i=1}log\\frac{1}{\\sqrt{2\\pi}\\sigma}exp\\left(-\\frac{(y^{(i)}-\\theta^T x^{(i)})^2}{2\\sigma^2}\\right) \\\\\n",
    "& = nlog\\frac{1}{{\\sqrt{2\\pi}\\sigma}} - \\frac{1}{\\sigma^2} \\cdot \\frac{1}{2}\\sum^n_{i=1}((y^{(i)}-\\theta^T x^{(i)})^2\n",
    "\\end{align*}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "显然，最大化$l(\\theta)$即最小化 $\\frac{1}{2}\\sum^n_{i=1}((y^{(i)}-\\theta^T x^{(i)})^2$。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这一结果即均方误差，因此用这个值作为代价函数来优化模型在统计学的角度是合理的。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2、线性回归损失函数、代价函数、目标函数\n",
    "* 损失函数(Loss Function)：度量单样本预测的错误程度，损失函数值越小，模型就越好。\n",
    "* 代价函数(Cost Function)：度量全部样本集的平均误差。\n",
    "* 目标函数(Object Function)：代价函数和正则化函数，最终要优化的函数。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "常用的损失函数包括：0-1损失函数、平方损失函数、绝对损失函数、对数损失函数等；常用的代价函数包括均方误差、均方根误差、平均绝对误差等。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<td bgcolor=#87CEEB>思考题：既然代价函数已经可以度量样本集的平均误差，为什么还要设定目标函数？</td>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 回答：\n",
    "当模型复杂度增加时，有可能对训练集可以模拟的很好，但是预测测试集的效果不好，出现过拟合现象，这就出现了所谓的“结构化风险”。结构风险最小化即为了防止过拟合而提出来的策略，定义模型复杂度为$J(F)$，目标函数可表示为："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\\underset{f\\in F}{min}\\, \\frac{1}{n}\\sum^{n}_{i=1}L(y_i,f(x_i))+\\lambda J(F)$$"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"download.png\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "例如有以上6个房价和面积关系的数据点，可以看到，当设定$f(x)=\\sum_{j=0}^{5}\\theta_jx_j$时，可以完美拟合训练集数据，但是，真实情况下房价和面积不可能是这样的关系，出现了过拟合现象。当训练集本身存在噪声时，拟合曲线对未知影响因素的拟合往往不是最好的。\n",
    "通常，随着模型复杂度的增加，训练误差会减少；但测试误差会先增加后减小。我们的最终目的时试测试误差达到最小，这就是我们为什么需要选取适合的目标函数的原因。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3、线性回归的优化方法"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1、梯度下降法"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "设定初始参数$\\theta$,不断迭代，使得$J(\\theta)$最小化：\n",
    "$$\\theta_j:=\\theta_j-\\alpha\\frac{\\partial{J(\\theta)}}{\\partial\\theta}$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\\begin{align*}\n",
    "\\frac{\\partial{J(\\theta)}}{\\partial\\theta} \n",
    "&= \\frac{\\partial}{\\partial\\theta_j}\\frac{1}{2}\\sum_{i=1}^{n}(f_\\theta(x)^{(i)}-y^{(i)})^2 \\\\\n",
    "&= 2*\\frac{1}{2}\\sum_{i=1}^{n}(f_\\theta(x)^{(i)}-y^{(i)})*\\frac{\\partial}{\\partial\\theta_j}(f_\\theta(x)^{(i)}-y^{(i)}) \\\\\n",
    "&= \\sum_{i=1}^{n}(f_\\theta(x)^{(i)}-y^{(i)})*\\frac{\\partial}{\\partial\\theta_j}(\\sum_{j=0}^{d}\\theta_jx_j^{(i)}-y^{(i)}))\\\\\n",
    "&= \\sum_{i=1}^{n}(f_\\theta(x)^{(i)}-y^{(i)})x_j^{(i)} \\\\\n",
    "\\end{align*}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "即："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\n",
    "\\theta_j = \\theta_j + \\alpha\\sum_{i=1}^{n}(y^{(i)}-f_\\theta(x)^{(i)})x_j^{(i)}\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "注：下标j表示第j个参数，上标i表示第i个数据点。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "将所有的参数以向量形式表示，可得："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\n",
    "\\theta = \\theta + \\alpha\\sum_{i=1}^{n}(y^{(i)}-f_\\theta(x)^{(i)})x^{(i)}\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "由于这个方法中，参数在每一个数据点上同时进行了移动，因此称为批梯度下降法，对应的，我们可以每一次让参数只针对一个数据点进行移动，即："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\n",
    "\\theta = \\theta + \\alpha(y^{(i)}-f_\\theta(x)^{(i)})x^{(i)}\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这个算法成为随机梯度下降法，随机梯度下降法的好处是，当数据点很多时，运行效率更高；缺点是，因为每次只针对一个样本更新参数，未必找到最快路径达到最优值，甚至有时候会出现参数在最小值附近徘徊而不是立即收敛。但当数据量很大的时候，随机梯度下降法经常优于批梯度下降法。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"download1.png\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "当J为凸函数时，梯度下降法相当于让参数$\\theta$不断向J的最小值位置移动"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "梯度下降法的缺陷：如果函数为非凸函数，有可能找到的并非全局最优值，而是局部最优值。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2、最小二乘法矩阵求解"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "令<br>\n",
    "$$ X = \\left[ \\begin{array} {cccc}\n",
    "(x^{(1)})^T\\\\\n",
    "(x^{(2)})^T\\\\\n",
    "\\ldots \\\\\n",
    "(x^{(n)})^T\n",
    "\\end{array} \\right] $$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "其中，"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$x^{(i)} = \\left[ \\begin{array} {cccc}\n",
    "x_1^{(i)}\\\\\n",
    "x_2^{(i)}\\\\\n",
    "\\ldots \\\\\n",
    "x_d^{(i)}\n",
    "\\end{array} \\right]$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "由于"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$Y = \\left[ \\begin{array} {cccc}\n",
    "y^{(1)}\\\\\n",
    "y^{(2)}\\\\\n",
    "\\ldots \\\\\n",
    "y^{(n)}\n",
    "\\end{array} \\right]$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$h_\\theta(x)$可以写作"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$h_\\theta(x)=X\\theta$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "对于向量来说，有"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$z^Tz = \\sum_i z_i^2$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "因此可以把损失函数写作"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$J(\\theta)=\\frac{1}{2}(X\\theta-Y)^T(X\\theta-Y)$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "为最小化$J(\\theta)$,对$\\theta$求导可得："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\\begin{align*}\n",
    "\\frac{\\partial{J(\\theta)}}{\\partial\\theta} \n",
    "&= \\frac{\\partial}{\\partial\\theta} \\frac{1}{2}(X\\theta-Y)^T(X\\theta-Y) \\\\\n",
    "&= \\frac{1}{2}\\frac{\\partial}{\\partial\\theta} (\\theta^TX^TX\\theta - Y^TX\\theta-\\theta^T X^TY - Y^TY) \\\\\n",
    "\\end{align*}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "中间两项互为转置，由于求得的值是个标量，矩阵与转置相同，因此可以写成"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\\begin{align*}\n",
    "\\frac{\\partial{J(\\theta)}}{\\partial\\theta} \n",
    "&= \\frac{1}{2}\\frac{\\partial}{\\partial\\theta} (\\theta^TX^TX\\theta - 2\\theta^T X^TY - Y^TY) \\\\\n",
    "\\end{align*}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "令偏导数等于零，由于最后一项和$\\theta$无关，偏导数为0。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "因此，"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\\frac{\\partial{J(\\theta)}}{\\partial\\theta}  = \\frac{1}{2}\\frac{\\partial}{\\partial\\theta} \\theta^TX^TX\\theta - \\frac{\\partial}{\\partial\\theta} \\theta^T X^TY\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "利用矩阵求导性质，<br>  \n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\n",
    "\\frac{\\partial \\vec x^T\\alpha}{\\partial \\vec x} =\\alpha \n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\n",
    "和\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\\frac{\\partial A^TB}{\\partial \\vec x} = \\frac{\\partial A^T}{\\partial \\vec x}B + \\frac{\\partial B^T}{\\partial \\vec x}A$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "\\begin{align*}\n",
    "\\frac{\\partial}{\\partial\\theta} \\theta^TX^TX\\theta \n",
    "&= \\frac{\\partial}{\\partial\\theta}{(X\\theta)^TX\\theta}\\\\\n",
    "&= \\frac{\\partial (X\\theta)^T}{\\partial\\theta}X\\theta + \\frac{\\partial (X\\theta)^T}{\\partial\\theta}X\\theta \\\\\n",
    "&= 2X^TX\\theta\n",
    "\\end{align*}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\\frac{\\partial{J(\\theta)}}{\\partial\\theta} = X^TX\\theta - X^TY\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "令导数等于零，"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$X^TX\\theta = X^TY$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\\theta = (X^TX)^{(-1)}X^TY\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "注：CS229视频中吴恩达的推导利用了矩阵迹的性质，可自行参考学习。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3、牛顿法"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"download2.png\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "通过图例可知(参考吴恩达CS229),"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$f(\\theta)' = \\frac{f(\\theta)}{\\Delta},\\Delta = \\theta_0 - \\theta_1$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$可求得，\\theta_1 = \\theta_0 - \\frac {f(\\theta_0)}{f(\\theta_0)'}$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "重复迭代，可以让逼近取到$f(\\theta)$的最小值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "当我们对损失函数$l(\\theta)$进行优化的时候，实际上是想要取到$l'(\\theta)$的最小值，因此迭代公式为："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\n",
    "\\theta :=\\theta-\\frac{l'(\\theta)}{l''(\\theta)}\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\n",
    "当\\theta是向量值的时候，\\theta :=\\theta - H^{-1}\\Delta_{\\theta}l(\\theta)\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "其中，$\\Delta_{\\theta}l(\\theta)$是$l(\\theta)$对$\\theta_i$的偏导数，$H$是$J(\\theta)$的海森矩阵，<br>\n",
    "$$H_{ij} = \\frac{\\partial ^2l(\\theta)}{\\partial\\theta_i\\partial\\theta_j}$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "问题：请用泰勒展开法推导牛顿法公式。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Answer：将$f(x)$用泰勒公式展开到第二阶，"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$f(x) = f(x_0) + f'(x_0)(x - x_0)+\\frac{1}{2}f''(x_0)(x - x_0)^2$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "对上式求导，并令导数等于0，求得x值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$f'(x) = f'(x_0) + f''(x_0)x -f''(x_0)x_0 = 0$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以求得，"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$x = x_0 - \\frac{f'(x_0)}{f''(x_0)}$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "牛顿法的收敛速度非常快，但海森矩阵的计算较为复杂，尤其当参数的维度很多时，会耗费大量计算成本。我们可以用其他矩阵替代海森矩阵，用拟牛顿法进行估计，"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4、拟牛顿法"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "拟牛顿法的思路是用一个矩阵替代计算复杂的海森矩阵H，因此要找到符合H性质的矩阵。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "要求得海森矩阵符合的条件，同样对泰勒公式求导$f'(x) = f'(x_0) + f''(x_0)x -f''(x_0)x_0$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "令$x = x_1$，即迭代后的值，代入可得："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$f'(x_1) = f'(x_0) + f''(x_0)x_1 - f''(x_0)x_0$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "更一般的，"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$f'(x_{k+1}) = f'(x_k) + f''(x_k)x_{k+1} - f''(x_k)x_k$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$f'(x_{k+1}) - f'(x_k)  = f''(x_k)(x_{k+1}- x_k)= H(x_{k+1}- x_k)$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$x_k$为第k个迭代值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "即找到矩阵G，使得它符合上式。\n",
    "常用的拟牛顿法的算法包括DFP，BFGS等，作为选学内容，有兴趣者可自行查询材料学习。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4、线性回归的评价指标"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "均方误差(MSE):$\\frac{1}{m}\\sum^{m}_{i=1}(y^{(i)} - \\hat y^{(i)})^2$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "均方根误差(RMSE)：$\\sqrt{MSE} = \\sqrt{\\frac{1}{m}\\sum^{m}_{i=1}(y^{(i)} - \\hat y^{(i)})^2}$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "平均绝对误差(MAE)：$\\frac{1}{m}\\sum^{m}_{i=1} | (y^{(i)} - \\hat y^{(i)} | $"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "但以上评价指标都无法消除量纲不一致而导致的误差值差别大的问题，最常用的指标是$R^2$,可以避免量纲不一致问题"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$R^2: = 1-\\frac{\\sum^{m}_{i=1}(y^{(i)} - \\hat y^{(i)})^2}{\\sum^{m}_{i=1}(\\bar y - \\hat y^{(i)})^2} =1-\\frac{\\frac{1}{m}\\sum^{m}_{i=1}(y^{(i)} - \\hat y^{(i)})^2}{\\frac{1}{m}\\sum^{m}_{i=1}(\\bar y - \\hat y^{(i)})^2} = 1-\\frac{MSE}{VAR}$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们可以把$R^2$理解为，回归模型可以成功解释的数据方差部分在数据固有方差中所占的比例，$R^2$越接近1，表示可解释力度越大，模型拟合的效果越好。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5、sklearn.linear_model参数详解："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "fit_intercept : 默认为True,是否计算该模型的截距。如果使用中心化的数据，可以考虑设置为False,不考虑截距。注意这里是考虑，一般还是要考虑截距\n",
    "\n",
    "normalize: 默认为false. 当fit_intercept设置为false的时候，这个参数会被自动忽略。如果为True,回归器会标准化输入参数：减去平均值，并且除以相应的二范数。当然啦，在这里还是建议将标准化的工作放在训练模型之前。通过设置sklearn.preprocessing.StandardScaler来实现，而在此处设置为false\n",
    "\n",
    "copy_X : 默认为True, 否则X会被改写\n",
    "\n",
    "n_jobs: int 默认为1. 当-1时默认使用全部CPUs ??(这个参数有待尝试)\n",
    "\n",
    "可用属性：\n",
    "\n",
    "coef_:训练后的输入端模型系数，如果label有两个，即y值有两列。那么是一个2D的array\n",
    "\n",
    "intercept_: 截距\n",
    "\n",
    "可用的methods:\n",
    "\n",
    "fit(X,y,sample_weight=None):\n",
    "X: array, 稀疏矩阵 [n_samples,n_features]\n",
    "y: array [n_samples, n_targets]\n",
    "sample_weight: 权重 array [n_samples]\n",
    "在版本0.17后添加了sample_weight\n",
    "\n",
    "get_params(deep=True)： 返回对regressor 的设置值\n",
    "\n",
    "predict(X): 预测 基于 R^2值\n",
    "\n",
    "score： 评估\n",
    "\n",
    "参考https://blog.csdn.net/weixin_39175124/article/details/79465558"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<table align =\"left\";background-color=\"#87CEEB\">\n",
    "<tr>\n",
    "    <td bgcolor=\"#87CEEB\"><font size=2>练习题：请用以下数据（可自行生成尝试，或用其他已有数据集）</font></td>\n",
    "</tr>\n",
    "<tr>\n",
    "<td  bgcolor=\"#87CEEB\"><font size=2>1、首先尝试调用sklearn的线性回归函数进行训练；</font></td>\n",
    "</tr>\n",
    "<tr>\n",
    "<td bgcolor=\"#87CEEB\"><font size=2>2、用最小二乘法的矩阵求解法训练数据；</font></td>\n",
    "</tr>\n",
    "<tr>    \n",
    "<td  bgcolor=\"#87CEEB\"><font size=2>3、用梯度下降法训练数据；</font></td>\n",
    "</tr>\n",
    "<tr>\n",
    "    <td  bgcolor=\"#87CEEB\"><font size=2>4、比较各方法得出的结果是否一致。</font></td>\n",
    "</tr>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "生成数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "#生成数据\n",
    "import numpy as np\n",
    "#生成随机数\n",
    "np.random.seed(1234)\n",
    "x = np.random.rand(500,3)\n",
    "#构建映射关系，模拟真实的数据待预测值,映射关系为y = 4.2 + 5.7*x1 + 10.8*x2，可自行设置值进行尝试\n",
    "y = x.dot(np.array([4.2,5.7,10.8]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 1、先尝试调用sklearn的线性回归模型训练数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "估计的参数值为：[ 4.2  5.7 10.8]\n",
      "R2:1.0\n",
      "预测值为: [85.2]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "from sklearn.linear_model import LinearRegression\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "# 调用模型\n",
    "lr = LinearRegression(fit_intercept=True)\n",
    "# 训练模型\n",
    "lr.fit(x,y)\n",
    "print(\"估计的参数值为：%s\" %(lr.coef_))\n",
    "# 计算R平方\n",
    "print('R2:%s' %(lr.score(x,y)))\n",
    "# 任意设定变量，预测目标值\n",
    "x_test = np.array([2,4,5]).reshape(1,-1)\n",
    "y_hat = lr.predict(x_test)\n",
    "print(\"预测值为: %s\" %(y_hat))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2、最小二乘法的矩阵求解"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "估计的参数值：[ 4.2  5.7 10.8]\n",
      "预测值为: [85.2]\n"
     ]
    }
   ],
   "source": [
    "class LR_LS():\n",
    "    def __init__(self):\n",
    "        self.w = None      \n",
    "    def fit(self, X, y):\n",
    "        # 最小二乘法矩阵求解\n",
    "        #============================= show me your code =======================\n",
    "        self.w = \n",
    "        #============================= show me your code =======================\n",
    "    def predict(self, X):\n",
    "        # 用已经拟合的参数值预测新自变量\n",
    "        #============================= show me your code =======================\n",
    "        y_pred = \n",
    "        #============================= show me your code =======================\n",
    "        return y_pred\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    lr_ls = LR_LS()\n",
    "    lr_ls.fit(x,y)\n",
    "    print(\"估计的参数值：%s\" %(lr_ls.w))\n",
    "    x_test = np.array([2,4,5]).reshape(1,-1)\n",
    "    print(\"预测值为: %s\" %(lr_ls.predict(x_test)))\n",
    "\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "3、梯度下降法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "估计的参数值为：[ 4.20000001  5.70000003 10.79999997]\n",
      "预测值为：[85.19999995]\n"
     ]
    }
   ],
   "source": [
    "class LR_GD():\n",
    "    def __init__(self):\n",
    "        self.w = None     \n",
    "    def fit(self,X,y,alpha=0.02,loss = 1e-10): # 设定步长为0.002,判断是否收敛的条件为1e-10\n",
    "        y = y.reshape(-1,1) #重塑y值的维度以便矩阵运算\n",
    "        [m,d] = np.shape(X) #自变量的维度\n",
    "        self.w = np.zeros((d)) #将参数的初始值定为0\n",
    "        tol = 1e5\n",
    "        #============================= show me your code =======================\n",
    "        while tol > loss:\n",
    "            # here\n",
    "            \n",
    "        #============================= show me your code =======================\n",
    "    def predict(self, X):\n",
    "        # 用已经拟合的参数值预测新自变量\n",
    "        y_pred = X.dot(self.w)\n",
    "        return y_pred  \n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    lr_gd = LR_GD()\n",
    "    lr_gd.fit(x,y)\n",
    "    print(\"估计的参数值为：%s\" %(lr_gd.w))\n",
    "    x_test = np.array([2,4,5]).reshape(1,-1)\n",
    "    print(\"预测值为：%s\" %(lr_gd.predict(x_test)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 参考"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "吴恩达 CS229课程"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "周志华 《机器学习》"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "李航 《统计学习方法》"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "https://hangzhou.anjuke.com/"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "https://www.jianshu.com/p/e0eb4f4ccf3e"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "https://blog.csdn.net/qq_28448117/article/details/79199835"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "https://blog.csdn.net/weixin_39175124/article/details/79465558"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
